#include <cstdio>
#include <cstdlib>
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include <cmath>
#include "DistanceManager.hpp"
#include "DataProcessor.hpp"
#include "RelationManager.hpp" //RelationPair
#include "BookName.hpp"
#include <vector>



int main(int argc, char *argv[])
{
    if (argc < 3)  {
        printf("Usage: %s data_path book_name_file\n", argv[0]);
        exit(-1);
    }


    FreqReader freq_reader;
    BookName book_name;


    if (freq_reader.Read(argv[1]) < 0) {
        printf("Freq table file read failed\n");
        return -1;
    }

    if (book_name.Read(argv[2]) < 0) {
        printf("book name file read failed\n");
        return -1;
    }



    struct dirent **filelist;
    int fnum = scandir(argv[1], &filelist, 0, alphasort);
    int last_bid = 0;
    std::vector<RelationPair> v;
    for(int i = 0; i <= fnum; i++) {
        const char *cstr;
        int cur_bid = 0;

        if (i != fnum) {
            cstr = filelist[i]->d_name;
            if (strncmp(cstr, "rel.", 4))
                continue;
            cur_bid = atoi(cstr + 4);
        } else 
            cur_bid = -1;

        if (cur_bid != last_bid) {
            DistanceManager distance_manager;
            sort(v.begin(), v.end());
            uint32_t w = v[0].weight;
            for(size_t i = 1; i < v.size(); i++) {
                if (v[i] == v[i - 1]) {
                    w += v[i].weight;
                } else {
                    uint32_t id1 = v[i - 1].id1;
                    uint32_t id2 = v[i - 1].id2;
                    uint32_t coincide = w;
                    double val = (double)coincide / sqrt((double)freq_reader.GetFreq(id1) * freq_reader.GetFreq(id2));
                    distance_manager.AddDistancePair(id1, id2, val);
                    w = v[i].weight;
                }
            }
            distance_manager.DumpResult(book_name);
            distance_manager.ClearData();
            v.clear();
            last_bid = cur_bid;
        }
        if (i == fnum)
            break;

        char filename[256];
        snprintf(filename, 256, "%s/%s", argv[1], cstr);
        
        printf("Reading file %s\n", filename);
        int fd = open(filename, O_RDONLY, 0644);
        if (fd < 0) {
            printf("file open failed %s\n", filename);
            exit(-1);
        }

        uint32_t fsize = lseek(fd, 0, SEEK_END);
        RelationPair *pair_list = reinterpret_cast<RelationPair*>(
                    mmap(NULL, fsize, PROT_READ, MAP_PRIVATE, fd, 0));

        uint32_t count = fsize / sizeof(RelationPair);
        for(uint32_t i = 0; i < count; i++) {
            v.push_back(pair_list[i]);
        }
        munmap(pair_list, fsize);
        close(fd);
        free(filelist[i]);
    }
    free(filelist);
}


